package com.xhj.mybatis.scripting;

import com.xhj.mybatis.util.MapUtil;

import java.util.HashMap;
import java.util.Map;

/**
 * LanguageDriverRegistry
 *
 * @author XJks
 * @description 脚本语言驱动注册中心
 */
public class LanguageDriverRegistry {

    /**
     * 存储所有已注册的 LanguageDriver 实现类及其实例的映射关系
     */
    private final Map<Class<? extends LanguageDriver>, LanguageDriver> LANGUAGE_DRIVER_MAP = new HashMap<>();

    /**
     * 默认的 LanguageDriver 实现类
     */
    private Class<? extends LanguageDriver> defaultDriverClass;

    /**
     * 注册一个 LanguageDriver 的类（Class），如果未注册则创建其实例并保存
     *
     * @param cls 需要注册的 LanguageDriver 类
     */
    public void register(Class<? extends LanguageDriver> cls) {
        if (cls == null) {
            // 如果传入的类为 null，抛出异常
            throw new IllegalArgumentException("null is not a valid Language Driver");
        }
        // 如果该类未注册，则创建其实例并放入 map
        MapUtil.computeIfAbsent(LANGUAGE_DRIVER_MAP, cls, k -> {
            try {
                // 通过反射调用无参构造方法创建实例
                return k.getDeclaredConstructor().newInstance();
            } catch (Exception ex) {
                // 创建失败则抛出异常
                throw new RuntimeException("Failed to load language driver for " + cls.getName(), ex);
            }
        });
    }

    /**
     * 注册一个 LanguageDriver 实例，如果该类未注册则保存该实例
     *
     * @param instance 需要注册的 LanguageDriver 实例
     */
    public void register(LanguageDriver instance) {
        if (instance == null) {
            // 如果实例为 null，抛出异常
            throw new IllegalArgumentException("null is not a valid Language Driver");
        }
        // 获取实例的实际类型
        Class<? extends LanguageDriver> cls = instance.getClass();
        // 如果该类型未注册，则将实例放入 map
        if (!LANGUAGE_DRIVER_MAP.containsKey(cls)) {
            LANGUAGE_DRIVER_MAP.put(cls, instance);
        }
    }

    /**
     * 根据 LanguageDriver 的类获取对应的实例
     *
     * @param cls 需要获取的 LanguageDriver 类
     * @return 已注册的 LanguageDriver 实例，未注册则返回 null
     */
    public LanguageDriver getDriver(Class<? extends LanguageDriver> cls) {
        return LANGUAGE_DRIVER_MAP.get(cls);
    }

    /**
     * 获取默认的 LanguageDriver 实例
     *
     * @return 默认的 LanguageDriver 实例
     */
    public LanguageDriver getDefaultDriver() {
        return getDriver(getDefaultDriverClass());
    }

    /**
     * 获取默认的 LanguageDriver 类
     *
     * @return 默认的 LanguageDriver 类
     */
    public Class<? extends LanguageDriver> getDefaultDriverClass() {
        return defaultDriverClass;
    }

    /**
     * 设置默认的 LanguageDriver 类，并自动注册该类
     *
     * @param defaultDriverClass 需要设置为默认的 LanguageDriver 类
     */
    public void setDefaultDriverClass(Class<? extends LanguageDriver> defaultDriverClass) {
        // 先注册该类
        register(defaultDriverClass);
        // 设置为默认类
        this.defaultDriverClass = defaultDriverClass;
    }

}
